using System;
using System.Threading.Tasks;
using AutoMapper;
using NBModular.Lib.Cache.Abstractions;
using NBModular.Module.WeChat.Application.WeChatService.ViewModels;
using NBModular.Module.WeChat.Domain.WeChat;
using NBModular.Module.WeChat.Domain.WeChat.Models;
using NBModular.Module.WeChat.Infrastructure;

namespace NBModular.Module.WeChat.Application.WeChatService
{
    public class WeChatService : IWeChatService
    {
        private readonly IMapper _mapper;
        private readonly IWeChatRepository _repository;
        private readonly ICacheHandler _cacheHandler;
        public WeChatService(
            IMapper mapper, 
            IWeChatRepository repository,
            ICacheHandler cacheHandler)
        {
            _mapper = mapper;
            _repository = repository;
            _cacheHandler = cacheHandler;
        }

        public async Task<IResultModel> Query(WeChatQueryModel model)
        {
            var result = new QueryResultModel<WeChatEntity>
            {
                Rows = await _repository.Query(model),
                Total = model.TotalCount
            };
            return ResultModel.Success(result);
        }

        public async Task<IResultModel> Add(WeChatAddModel model)
        {
            var entity = _mapper.Map<WeChatEntity>(model);
            if (await _repository.ExistsAsync(e=>e.AppId== model.AppId))
            {
                return ResultModel.HasExists;
            }

            var result = await _repository.AddAsync(entity);
            return ResultModel.Result(result);
        }

        public async Task<IResultModel> Delete(Guid id)
        {
            var result = await _repository.DeleteAsync(id);
            return ResultModel.Result(result);
        }

        public async Task<IResultModel> Edit(Guid id)
        {
            var entity = await _repository.GetAsync(id);
            if (entity == null)
                return ResultModel.NotExists;

            var model = _mapper.Map<WeChatUpdateModel>(entity);
            return ResultModel.Success(model);
        }

        public async Task<IResultModel> Update(WeChatUpdateModel model)
        {
            var entity = await _repository.GetAsync(model.Id);
            if (entity == null)
                return ResultModel.NotExists;

            _mapper.Map(model, entity);

            if (await _repository.ExistsAsync(e => e.AppId == model.AppId && e.Id != model.Id))
            {
                return ResultModel.HasExists;
            }

            var result = await _repository.UpdateAsync(entity);

            return ResultModel.Result(result);
        }

        public async Task<IResultModel> GetTokenAsync(string appid) 
        {
            string key = appid;
            if (_cacheHandler.TryGetValue(CacheKeys.WECHAT_AUTH_GLOBAL_ACCESS_TOKEN + key, out string result))
                return ResultModel.Success(result);

            result =await _repository.GetTokenAsync(appid);
            if (result == null)
                return ResultModel.NotExists;

            var json = result.ToJObject();
            if (!json.ContainsKey("errcode"))
            {
                int minutes = 1;
                if (json.ContainsKey("create_time"))
                {
                    var create_time = json["create_time"].ToDateTime();
                    if (json.ContainsKey("expires_in"))
                    {
                        var expires_in = json["expires_in"].ToInt() - 100;
                        if (create_time.AddSeconds(expires_in) > DateTime.Now)
                            minutes = (create_time.AddSeconds(expires_in) - DateTime.Now).TotalMinutes.ToInt();
                    }
                }
                await _cacheHandler.SetAsync(CacheKeys.WECHAT_AUTH_GLOBAL_ACCESS_TOKEN + key, result, minutes);
            }
               
            return ResultModel.Success(result);
        }
    }
}
